package classes.form {
	import classes.Label;

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;

	/**
	 * @author dennyshess
	 */
	public class Slider extends FormElement {

		private var w : Number;
		private var totalSteps : Number;
		private var startStep : Number;

		private var bar : Sprite = new Sprite();
		private var container : Sprite;
		private var minHandle : SliderControler;
		private var maxHandle : SliderControler;
		private var usedController : SliderControler; // which controller is in use

		private var sliderBG : *;
		private var sliderActive : *;
		private var sliderControllerLeft : *;
		private var sliderControllerRight : *;

		
		public function Slider( totalSteps : Number, w : Number, startStep : Number, label : String, sliderBG : *, sliderActive : *, sliderControllerLeft : *, sliderControllerRight : * ) : void {
			super();
			this.w = w;
			this.totalSteps = totalSteps;
			this.startStep = startStep;
			
			this.sliderBG = sliderBG;
			this.sliderActive = sliderActive;
			this.sliderControllerLeft = sliderControllerLeft;
			this.sliderControllerRight = sliderControllerRight;
			addEventListener(Event.ADDED_TO_STAGE, generate);
			addEventListener(Event.ENTER_FRAME, redraw);		
		}

		private function generate( e : Event) : void {
			this.container = new Sprite();
			this.addChild(this.container);
			
			/*
			 * Create background
			 */
			var box : Sprite = new Sprite();
			if( sliderBG ) {
				box.addChild(sliderBG);
			} else {
				box.graphics.beginFill(0xCDCDCD);
				box.graphics.drawRect(0, 0, this.w, 10);
				box.graphics.endFill();
			}
			
			/*
			 * Create Bar to show size
			 */
			if( sliderActive ) {
				this.bar.addChild(sliderActive);
			} else {
				this.bar.graphics.beginFill(0xFF0000);
				this.bar.graphics.drawRect(0, 0, 10, 10);
				this.bar.graphics.endFill();
				this.bar.alpha = 0.5;
			}
			this.bar.y = 1;
			box.addChild(this.bar);
			container.addChild(box);
			
			/*
			 * Create controllers
			 */
			this.minHandle = new SliderControler(sliderControllerLeft);
			this.minHandle.x = Math.round(-this.minHandle.width / 2);
			this.minHandle.y = -20;
			container.addChild(this.minHandle);

			this.maxHandle = new SliderControler(sliderControllerRight);
			this.maxHandle.x = Math.round(this.width - this.maxHandle.width);
			this.maxHandle.y = -20;
			container.addChild(this.maxHandle);
			
			/*
			 * Create listeners for controllers
			 */
			this.minHandle.addEventListener(MouseEvent.MOUSE_DOWN, toggleSlider);
			this.minHandle.addEventListener(MouseEvent.MOUSE_UP, toggleSlider);
			
			this.maxHandle.addEventListener(MouseEvent.MOUSE_DOWN, toggleSlider);
			this.maxHandle.addEventListener(MouseEvent.MOUSE_UP, toggleSlider);
			
			// resize bar and update labels
			init();
		}

		private function init() : void {
			stage.addEventListener(MouseEvent.MOUSE_UP, resetUsedController);
			var newWidth : Number = calcSize();
			this.bar.width = newWidth;
			this.bar.x = calcPosition();	
			this.maxHandle.updateLabel(getPosValue(this.maxHandle.x + this.maxHandle.width / 2));
			this.minHandle.updateLabel(getPosValue(this.minHandle.x + this.minHandle.width / 2));
		}

		private function redraw(e : Event) : void {
			if( usedController ) {
				var newX : Number = mouseX - this.usedController.width / 2; 
				if( newX < 0 - this.usedController.width / 2 ) newX = 0;
				if( newX > this.w ) newX = this.w;
				
				update(newX, this.usedController);
				saveValue(); // save Value to formValue
			}			
		}

		private function update( newX : Number, controller : SliderControler ) : void {
			controller.x = Math.round(newX);
			var newWidth : Number = calcSize();
			this.bar.width = Math.round(newWidth);
			this.bar.x = Math.round(calcPosition());
			controller.updateLabel(getPosValue(controller.x + controller.width / 2));
		}

		private function calcPosition() : Number {
			var pos : Number = this.minHandle.x + this.minHandle.width / 2;
			return pos;
		}

		private function calcSize() : Number {
			var pointMin : Number = this.minHandle.x + (this.minHandle.width / 2);
			var pointMax : Number = this.maxHandle.x + (this.maxHandle.width / 2);
			return pointMax - pointMin;		
		}

		private function toggleSlider(e : MouseEvent) : void {
			if( e.type == 'mouseDown' ) this.usedController = SliderControler(e.target);
			else resetUsedController(e);
		}

		
		/*
		 * carete a Scalegrid
		 */
		public function createScale(color : uint = 0x000000) : void {
			var scale : Sprite = new Sprite();
			for( var i : int = 0;i < this.totalSteps;i++ ) {
				var line : Sprite = new Sprite();
				line.graphics.beginFill(color);
				line.graphics.drawRect(0, 0, 1, 10);
				line.graphics.endFill();
				line.x = Math.round(getStepPos(i));
				scale.addChild(line);
			}  
			this.container.addChild(scale);
		}

		
		private function reposController( controller : SliderControler ) : void {
			if( controller ) {
				var controllerPos : Number = controller.x + controller.width / 2;
				
				for( var i : int = 0;i < this.totalSteps;i++ ) {
					if( getStepPos(i) > controllerPos && getStepPos(i - 1) < controllerPos ) {
						// Middle of the two steps;
						var middleOfToSteps : Number = (getStepPos(i) - getStepPos(i - 1)) / 2 + getStepPos(i - 1);
						
						// Jump to Step on the left or right side
						var newPos : Number = middleOfToSteps > controllerPos ? getStepPos(i - 1) : getStepPos(i);
						
						// Update Handles
						update(newPos - controller.width / 2, controller);
					}
				}
			}
		}	

		private function getStepPos(step : int) : Number {
			return step * (this.w / this.totalSteps);
		}

		private function getPosValue(xValue : Number) : Number {
			var stepSize : Number = (this.w / this.totalSteps);
			return Math.round((xValue / stepSize) + startStep);
		}

		/*
		 * If the mouse goes up, reset the used controller to null
		 */
		private function resetUsedController(e : MouseEvent) : void {
			reposController(this.usedController);
			this.usedController = null;
		}

		private function saveValue() : void {
			var min : Number = getPosValue(this.minHandle.x + this.minHandle.width / 2);
			var max : Number = getPosValue(this.maxHandle.x + this.maxHandle.width / 2);
			this.formValue = new Array();
			this.formValue.push(min);
			this.formValue.push(max);
		}
	}
}
